/**************************************************************************
*
*	platform.c
*
*  Copyright 2007,2008,2009 Steve Stancliff
*
*  Part of the TAOSF SSA system.
*
*  This module provides the main functions for SSA mobile platforms.
*
*
***************************************************************************
*
*  version 1.2.2, 3/5/09, SBS
*    - increase telemetry output rate
*
*  version 1.2.1, 2/22/09, SBS
*    - cleanup
*    - add #ifdef DEBUG_USESYSLOG
*
*  version 1.2, 2/2/09, SBS
*    - commandfile fetching/parsing is now done in a separate thread
*
*  version 1.1.1, 1/30/09, SBS
*    - change platformstatus_ parameters (don't pass entire CONFIGDATA)
*    - move controller_InitDefault() into platformstatus_Init
*
*  version 1.1, 1/9/09, SBS
*    - move updating and memory of STATUS/COMMAND into platformstatus.c
*    - add startup for controller() 
*
*  version 1.0.12, 1/8/09, SBS
*    - LOGLEVEL_INFO --> LOGLEVEL_DEBUG
*
*  version 1.0.11, 1/5/09, SBS
*    - add MOVEREALFAST and INCREMENTBATTERY #defines for testing throughput
*
*  version 1.0.10, 1/2/09, SBS
*    - cleanup
*
*  version 1.0.9, 12/31/08, SBS
*    - move parameters into configuration struct/file
*
*  version 1.0.8, 12/2/08, SBS
*    - separate ip addresses for command and telemetry
*    - modify main loop delay to consider time that has elapsed instead of
*      sleeping regardless
*    - rearrange mainloop() and its subfunctions for clarity
*
*  version 1.0.7, 11/28/08, SBS
*    - change to new commandfile socket read function
*    - modify calls into commandfile_ and telemfile_ to pass filespec
*
*  version 1.0.6, 11/26/08, SBS
*    - change to new telemfile socket write function
*    - change how it retrieves science data -> put into struct instead
*      of just writing to file
*    - cleanup
*
*  version 1.0.5, 11/12/08, SBS
*    - use new version of telemfile_WriteSciData()
*
*  version 1.0.4, 10/17/08, SBS
*    - initial version of platform.c based on simulator.c
*
*  version 1.0.3, 10/4/08, SBS
*    - documentation
*
*  version 1.0.2, 7/12/08, SBS
*    - modifications to use data/ directory
*
*  version 1.0.1, 4/3/08, SBS
*    - correct a couple of problems when DEBUG was not defined
*
*  version 1.0, 3/5/08, SBS
*    - change to using 'cp' for local dataserver files
*    - minor cleanup
*
*  version 0.9.1, 2/21/08, SBS
*    - change initcmdfiles to write files instead of copying
*
*  version 0.9, 12/17/07, SBS
*    - almost there...
*
*  version 0.1, 12/08/07, SBS
*    - first version, derived from irc_client.c
*
*
***************************************************************************
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful, but 
*  WITHOUT ANY WARRANTY; without even the implied warranty of 
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
*  General Public License for more details.
*
*  You should have received a copy of the GNU General Public License 
*  along with this program; if not, write to the Free Software Foundation, 
*  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 
*
**************************************************************************/
/**
*  @defgroup platform
*  @brief
*  This module provides the main functions for SSA mobile platforms.
*/
/**
*  @file 
*  @ingroup platform
*  @brief
*  This module provides the main functions for SSA mobile platforms.
*  <hr>
**/

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <syslog.h>

#include <stdint.h>
#include "types.h"

#include "config.h"

#include <time.h>
#include <sys/timeb.h>
#include "delay.h"

#include "waypoints.h"
#include "platform_types.h"
#include "platform_modes.h"
#include "status.h"
#include "telemfile.h"

#include "command.h"
#include "commandfile.h"

#ifdef DEBUG
#include "logfile.h"
#endif

#include "controller.h"
#include "platformstatus.h"


#define CMDSTRLEN 512
#define FILESPECLEN 256
#define PORTSTRLEN 32

#define CFGFILENAME "platform.cfg"


#define SLEEPDELAY (0.05)
#define LOOPINTERVAL (0.1)
#define OUTPUTINTERVAL (2)	// network updates at NETINTERVAL x LOOPINTERVAL
#define INPUTINTERVAL  (5)



/********************************************************/

#define WRITELOCALFILE
//#define MOVEREALFAST


/**
***************************************************************************
*
* output_status()
*/
/** 
*
* @brief
*  Writes status to telemetry file and/or to telemserver
*
*  Parameters:
*    - s - the status struct to write
*    - cf - configuration data
*
*  Returns:
*    - none
*
**************************************************************************/
static void output_status(
			CONFIGDATA cf)
{
	static STATUS oldstatus;
	static int memory = 0;

	STATUS s;
	
	s = platformstatus_GetStatus();

	if(memory != 0){
		if(status_compareStatus(oldstatus,s) == 0){
			return;
		}
	}	

	#ifdef WRITELOCALFILE
	char filespec[FILESPECLEN];
	
	snprintf(filespec,FILESPECLEN,"%s/%s%d.%s"
				,cf.localdatapath
				,cf.telemfilebase
				,cf.robotnumber
				,cf.telemfileext);
	
	telemfile_WriteFileDirect(filespec, s);

	#endif

	#ifdef USE_NETWORK
	char port[PORTSTRLEN];
	
	snprintf(port,sizeof(port),"%d"
				,cf.telemserver_baseportput + cf.robotnumber);
	
	telemfile_WriteTelemServer(cf.telemserver_ipaddr,port,s);
	#endif		

	if(memory==0){
		memory=1;
	}
	oldstatus = s;

	return;
}

	
/**
***************************************************************************
*
* mainloop()
*/
/** 
*
* @brief
*  Loops forever, updating telemetry and commands
*
*  Parameters:
*    - cf - configuration data struct
*
*  Returns:
*    - none
*
**************************************************************************/
static void mainloop(
			CONFIGDATA cf)
{
	#ifndef MOVEREALFAST		
	struct timeb starttime,endtime;
	TIMESPEC delay;
	double delta;
	#endif
	
	int i,j;
	COMMAND c;
		
	#ifndef MOVEREALFAST		
	delay = delay_setdelay(SLEEPDELAY);
	#endif
	
	i = 0;
	j=0;
	
	while(1){
		
		printf(".");
		fflush(stdout);
		
		#ifndef MOVEREALFAST		
		ftime(&starttime);
		#endif
	
		if(i==INPUTINTERVAL){	
			c = commandfile_GetStatus();
			i=0;
		}else{
			i++;
		}
	
		platformstatus_SetCommand(c);

		platformstatus_UpdateStatus();		
	
		if(j==OUTPUTINTERVAL){
			output_status(cf);
			j=0;
		}else{	
			j++;
		}
		
		#ifndef MOVEREALFAST		
		ftime(&endtime);	
		
		delta = delay_deltatime(starttime,endtime);
		
		while(delta < (LOOPINTERVAL-SLEEPDELAY)){
			delay_sleep(&delay);
			ftime(&endtime);	
			delta = delay_deltatime(starttime,endtime);		
		}
		#endif

	}
	
	return;
}


/**
***************************************************************************
*
* OpenLog()
*/
/** 
*
* @brief
*  Initializes logging subsystem
*
*  Parameters:
*    - cf - configuration data struct
*
*  Returns:
*    - none
*
**************************************************************************/
static void OpenLog(
			CONFIGDATA cf)
{

	#ifdef DEBUG
	#ifdef DEBUG_USESYSLOG
	logfile_OpenSyslog(LOGFACILITY);
	#else
	logfile_OpenFile(cf.logfilename);
	#endif
	
	logfile_LogLevelSet(cf.loglevel);

	logfile_LogLevelPrint(LOGLEVEL_INFO," ");
	logfile_LogLevelPrint(LOGLEVEL_INFO
				,"*******************************************");		
	logfile_LogLevelPrint(LOGLEVEL_INFO,"SSA PLATFORM STARTUP");
	logfile_LogLevelPrint(LOGLEVEL_INFO
				,"*******************************************");		
	logfile_LogLevelPrint(LOGLEVEL_INFO," ");
	#endif	
	
	return;
}


/**
***************************************************************************
*
* InterruptCallback()
*/
/** 
*
* @brief
*
* 
**************************************************************************/
void InterruptCallback(
			int signum)
{
	#ifdef DEBUG
	char str[LOGSTRLEN];

	snprintf(str,LOGSTRLEN, "\nExiting on signal %d!", signum);
	logfile_LogLevelPrint(LOGLEVEL_CRITICAL,str);
	logfile_CloseFile();
	#endif

	printf("\nExiting on signal %d!", signum);
	exit(signum);
}


/**
***************************************************************************
*
* SetIntCallback()
*/
/** 
*
* @brief
*
* 
*
**************************************************************************/
static void SetIntCallback()
{
	signal(SIGINT, InterruptCallback);
	signal(SIGTERM, InterruptCallback);
	signal(SIGQUIT, InterruptCallback);
	signal(SIGHUP, InterruptCallback);
}


/**
***************************************************************************
*
* main()
*/
/** 
*
* @brief
*  Entry point for program.  Reads configuration from
*    command line and config file, opens log file, 
*    then hands off to mainloop()
*
*  Parameters:
*    - argc
*    - argv
*
*  Returns:
*    - not used
*
**************************************************************************/
int main(
			int argc
			,char **argv)
{
		
	
	CONFIGDATA cf;		

	srand(time(NULL));

	cf = config_readconfig(argc,argv,CFGFILENAME);

	OpenLog(cf);
	
	SetIntCallback();

	config_PrintConfig(cf);

	commandfile_StartThread(cf);	

	platformstatus_Init(cf.robotnumber-1,cf.robotname,cf.platformtype);
	
	controller_Start();
	
	mainloop(cf);
	
	return(0);
}

